package com.buba.log;

import com.buba.log.dao.OperateLogDao;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 用户操作日志切面类
 * @Aspect 定义该类为切面类
 * @Component  当不属于任何层级的类时，使用这个注解
 */
@Component
@Aspect
public class LogAspect {
    @Autowired
    private OperateLogDao operateLogDao;


    /**
     * @Before 前置通知
     * @JoinPoint 封装了SpringAOP中切面方法的信息
     */
    @Before("execution(* com.buba.*.service.*.*(..))")
    public void addOperateLog(JoinPoint joinPoint){
        System.out.println("触发前置通知");
        //Signature 封装了触发该通知的类信息
        Signature signature = joinPoint.getSignature();
        //获取触发通知的类名
        System.out.println(signature.getDeclaringTypeName());
        //获取触发通知的方法
        System.out.println(signature.getName());
        //获取触发该方法的参数
        System.out.println(Arrays.toString(joinPoint.getArgs()));
    }


    /**
     * 后置通知，没有异常时触发
     * @AfterReturning pointcut定义切点   returning返回值名字
     * @param joinPoint
     * @param ret
     */
    @AfterReturning(pointcut = "execution(* com.buba.*.service.*.*(..))",returning = "ret")
    public void addOperateLog2(JoinPoint joinPoint,Object ret){
        System.out.println("——————————触发后置通知————————");
        System.out.println(ret);

    }

    /**
     * 环绕通知
     * ProceedingJoinPoint继承自JoinPoint
     * @param joinPoint
     */
    @Around(value = "execution(* com.buba.*.service.*.*(..))")
    public Object addOperateLog3(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("——————————触发环绕通知  Service前————————");


        //是否继续执行   以原本方法的参数运行执行
//        Object proceed = joinPoint.proceed();
        Object proceed = joinPoint.proceed(joinPoint.getArgs());
        //环绕通知能够改变方法传递的参数
//        Object proceed = joinPoint.proceed(new Object[]{""});
        System.out.println("——————————触发环绕通知  Service后————————");
//环绕通知也能够改变方法返回值
        return proceed;

    }
}
